﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.Windows.Threading;
using RemotingMessage;

namespace ServerVideoChat
{
    [ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
    public class ServiceVideoChat : IServiceVideoChat
    {
        private DispatcherTimer tmrPing = new DispatcherTimer(){Interval = TimeSpan.FromSeconds(1)};
        void tmrPing_Tick(object sender, EventArgs e)
        {
            //tmrPing.Stop();
            //var t = App.ViewModel.Clients.Where(p => p.IsOnline == false).ToList();
            //if (t.Count > 0)
            //{
            //    foreach (ClientInfo cl in t)
            //    {
            //        App.ViewModel.Clients.Remove(cl);
            //    }

            //    var clientList = App.ViewModel.Clients.Select(p => p.UserName).ToArray();
            //    foreach (var cl in App.ViewModel.Clients)
            //    {
            //        //cl.CallBackVideoChat.ActiveClientList(clientList);
            //    }
            //}

            //Ping();
            //tmrPing.Start();
        }

        public ServiceVideoChat()
        {
            //App.viewModel.ServiceVideoChat = this;
            //tmrPing.Tick += new EventHandler(tmrPing_Tick);
            //tmrPing.Start();
        }

        public void NewVideoFrameRecived(byte[] btVideoFrame)
        {
            //var t = App.ViewModel.Clients.Where(p => p.IsIpVideoSending && p.IsOnline);
           // foreach (var cl in t)
            {
                try
                {
                    //cl.CallBackVideoChat.IPVideoSample(btVideoFrame);
                }
                catch (CommunicationException ex)
                {
                    //cl.IsOnline = false;
                }
            }
        }

        #region Events
        public event EventHandler<ServiceVideoChatEventArg> ClientJoin;
        private void OnClientJoin(ClientInfo clientInfo)
        {
            if (ClientJoin != null)
            {
                ClientJoin(this, new ServiceVideoChatEventArg(clientInfo));
            }
        }

        public event EventHandler<ServiceMessageEventArg> ClientMessage;
        private void OnClientMessage(string message, ClientInfo from, ClientInfo to)
        {
            if (ClientMessage != null)
            {
                ClientMessage(this, new ServiceMessageEventArg(message, from, to));
            }
        }

        public event EventHandler<ServiceVideoChatEventArg> ClientLeave;
        private void OnClientLeave(ClientInfo clientInfo)
        {
            if (ClientLeave != null)
            {
                ClientLeave(this, new ServiceVideoChatEventArg(clientInfo));
            }
        }
        #endregion

        public void Join(string userName, string machineName, string softwareVersion)
        {
            if (App.ViewModel.Clients.Where(p => p.UserName == userName).Any()) return;
            IVideoChatCallback callbacChat = OperationContext.Current.GetCallbackChannel<IVideoChatCallback>();
            //ClientInfo cl = new ClientInfo(userName, machineName, softwareVersion) { IsOnline = true, CallBackVideoChat = callbacChat };
            //cl.CallBackVideoChat.ActiveClientList(App.ViewModel.Clients.Select(p => p.UserName).ToArray());
            //App.ViewModel.Clients.Add(cl);
            //OnClientJoin(cl);
            //App.ViewModel.AddLogMessage("Клиент " + cl.UserName + " подкличился к сервису");
            foreach (ClientInfo cls in App.ViewModel.Clients)
            {
                //cls.CallBackVideoChat.UserJoin(cl.UserName);
            }
        }

        public void SendMessage(string clientToName, string message)
        {
            //if (App.ViewModel.Clients.Where(p => p.UserName == clientToName).Count() != 1) return;
            //var clTo = App.ViewModel.Clients.Where(p => p.UserName == clientToName).Single();

            //IVideoChatCallback callback = OperationContext.Current.GetCallbackChannel<IVideoChatCallback>();
            //var clFrom = App.ViewModel.Clients.Where(p => p.CallBackVideoChat == callback).Single();

            ////clTo.CallBackVideoChat.ReceiveMessage(clFrom.UserName, message);
            //OnClientMessage(message, clFrom, clTo);
            //App.ViewModel.AddLogMessage("Клиент " + clFrom.UserName + " отправил сообщение клиенту " + clTo.UserName + ".\nСодержимое сообщения: " + message);

        }

        public void Leave()
        {
            //IVideoChatCallback callback = OperationContext.Current.GetCallbackChannel<IVideoChatCallback>();
            //if (!App.ViewModel.Clients.Where(p => p.CallBackVideoChat == callback).Any()) return;

            //var clLeave = App.ViewModel.Clients.Where(p => p.CallBackVideoChat == callback).Single();
            //foreach (ClientInfo cls in App.ViewModel.Clients)
            //{
            //    //cls.CallBackVideoChat.UserLeave(clLeave.UserName);
            //}
            //App.ViewModel.Clients.Remove(clLeave);
            //OnClientLeave(clLeave);
            //App.ViewModel.AddLogMessage("Клиент " + clLeave.UserName + " отключился от сервиса");
        }

        public void GetActiveClientList()
        {
            //IVideoChatCallback callback = OperationContext.Current.GetCallbackChannel<IVideoChatCallback>();
            //if (!App.ViewModel.Clients.Where(p => p.CallBackVideoChat == callback).Any()) return;
            //var t = App.ViewModel.Clients.Where(p => p.CallBackVideoChat == callback).Single();
            ////t.CallBackVideoChat.ActiveClientList(App.ViewModel.Clients.Select(p => p.UserName)
            //                                       //.ToArray());
            //App.ViewModel.AddLogMessage("Список активных пользователей отправлен клиенту " + t.UserName);
        }

        public void Ping()
        {
            //foreach (var cl in App.ViewModel.Clients.Where(p => p.IsOnline))
            //{
            //    try
            //    {
            //        cl.CallBackVideoChat.Ping();
            //    }
            //    catch(CommunicationException ex)
            //    {
            //        App.ViewModel.Clients.Where(p => p == cl).Single().IsOnline = false;
            //    }
            //}
        }

        public void PingRequest()
        {
            //IVideoChatCallback callback = OperationContext.Current.GetCallbackChannel<IVideoChatCallback>();
            //if (!App.ViewModel.Clients.Where(p => p.CallBackVideoChat == callback).Any()) return;
            //App.ViewModel.Clients.Where(p => p.CallBackVideoChat == callback).Single().IsOnline = true;
        }

        public void StartIPVideo()
        {
            //IVideoChatCallback callbacChat = OperationContext.Current.GetCallbackChannel<IVideoChatCallback>();
            //if (!App.ViewModel.Clients.Where(p => p.CallBackVideoChat == callbacChat).Any()) return;
            //var t = App.ViewModel.Clients.Where(p => p.CallBackVideoChat == callbacChat).Single();
            //t.IsIpVideoSending = true;
            //App.ViewModel.AddLogMessage("Клиент " + t.UserName + " начал прием IP-видео" + t.UserName);

        }

        public void StopIPVideo()
        {
            //IVideoChatCallback callbacChat = OperationContext.Current.GetCallbackChannel<IVideoChatCallback>();
            //if (!App.ViewModel.Clients.Where(p => p.CallBackVideoChat == callbacChat).Any()) return;
            //var t = App.ViewModel.Clients.Where(p => p.CallBackVideoChat == callbacChat).Single();
            //t.IsIpVideoSending = false;
            //App.ViewModel.AddLogMessage("Клиент " + t.UserName + " прекратил прием IP-видео" + t.UserName);
        }

        public void StartIPAudio()
        {
           // IVideoChatCallback callbacChat = OperationContext.Current.GetCallbackChannel<IVideoChatCallback>();
           // if (!App.ViewModel.Clients.Where(p => p.CallBackVideoChat == callbacChat).Any()) return;
           // var t = App.ViewModel.Clients.Where(p => p.CallBackVideoChat == callbacChat).Single();
           //t.IsIpAudioSending = true;
           //App.ViewModel.AddLogMessage("Клиент " + t.UserName + " начал прием IP-аудио" + t.UserName);
        }

        public void StopIPAudio()
        {
            //IVideoChatCallback callbacChat = OperationContext.Current.GetCallbackChannel<IVideoChatCallback>();
            //if (!App.ViewModel.Clients.Where(p => p.CallBackVideoChat == callbacChat).Any()) return;
            //var t = App.ViewModel.Clients.Where(p => p.CallBackVideoChat == callbacChat).Single();
            //t.IsIpAudioSending = false;
            //App.ViewModel.AddLogMessage("Клиент " + t.UserName + " прекратил прием IP-аудио" + t.UserName);
        }

        public void GetIPVideoSample()
        {
            //IServiceIPvideoCallback callback = OperationContext.Current.GetCallbackChannel<IServiceIPvideoCallback>();
            //if (!App.ViewModel.Clients.Where(p => p.CallBackVideoChat == callback).Any()) return;
            //var t = App.ViewModel.Clients.Where(p => p.CallBackVideoChat == callback).Single();
            //t.CallBackVideoChat.IPVideoSample(App.ViewModel.IPVideoSample);
        }

        public void GetIPAudioSample()
        {
            throw new NotImplementedException();
        }
    }

    

    [Serializable]
    public class ServiceVideoChatEventArg : EventArgs
    {
        public ServiceVideoChatEventArg(ClientInfo clientInfo)
        {
            Client = clientInfo;
        }

        public ClientInfo Client { get; private set; }
    }

    [Serializable]
    public class ServiceMessageEventArg : EventArgs
    {
        public ServiceMessageEventArg(string message, ClientInfo from, ClientInfo to)
        {
            Message = message;
            From = from;
            To = to;
        }

        public string Message { get; private set; }
        public ClientInfo From { get; private set; }
        public ClientInfo To { get; private set; }
    }


}
